﻿
using System;
using System.CodeDom;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;

using Game.Map;
using Microsoft.CSharp;

namespace SL
{
    public partial class CommandLine : UserControl
    {
        IGameMapView _GameMapView;
        
        readonly static string MAIN_CLASS = @"
class MainClass
{
    public static void Main(string[] args)
    {
    }
}
";
        
        public CommandLine(IGameMapView gameMapView)
        {
            _GameMapView = gameMapView;
            InitializeComponent();
            
            this.textBox1.Text = @"
class Script
{
    public void Run(Game.Map.IGameMapView map)
    {
        map.ViewFields[0].IsVisible = true;
    }
}
";
        }
        
        void button1_Click(object sender, RoutedEventArgs e)
        {
            string[] code = new string[] 
            { 
                this.textBox1.Text, MAIN_CLASS
            };
            
            CompileCSharpCode(code);
        }
        
        public bool CompileCSharpCode(string[] code)
        {
            Dictionary<string, string> provOptions = new Dictionary<string, string>();
            provOptions.Add("CompilerVersion", "v4.0");
            CSharpCodeProvider provider = new CSharpCodeProvider(provOptions);
        
            CompilerParameters cp = new CompilerParameters();
            
            AssemblyName[] names = 
                Assembly.GetEntryAssembly().GetReferencedAssemblies();
            GetReferencedAssemblies(cp, names);
            cp.GenerateExecutable = true;
            cp.GenerateInMemory = true;
        
            CompilerResults cr = provider.CompileAssemblyFromSource(cp, code);
            
            if (cr.Errors.Count > 0)
            {
                Console.WriteLine("Errors building {0}", cr.PathToAssembly);
                foreach (CompilerError ce in cr.Errors)
                {
                    this.textBox2.Text += ce.ErrorText + "\r\n";
                }
            }
            else
            {
                this.textBox2.Text += "Success\r\n";
                
                StringWriter swriter = new StringWriter();
                IndentedTextWriter writer = new IndentedTextWriter(swriter);
                writer.WriteLine();
                
                Type t = cr.CompiledAssembly.GetType("Script");
                object obj = Activator.CreateInstance(t, new object[] {});
                
                MethodInfo m = t.GetMethod("Run");
                m.Invoke(obj, new object[] { _GameMapView });
                
                writer.Flush();
                this.textBox2.Text += swriter.ToString();
                
//                string[] parameters = new string[]{"Hello"};
//                MethodInfo entry = cr.CompiledAssembly.EntryPoint;
//                entry.Invoke(null, new object[1] { parameters });  
            }
            
            if (cr.Errors.Count > 0)
            {
                return false;
            }
            else
            {
                return true;
            }
        }
        
        static void GetReferencedAssemblies(
            CompilerParameters compilerParams, 
            AssemblyName[] names)
        {
            string s = @"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\WindowsBase.dll";
            compilerParams.ReferencedAssemblies.Add(s);
            
            foreach (AssemblyName name in names)
            {
                string asm;
                if (name.Name != "mscorlib" &&
                    name.Name.StartsWith("System.") == false &&
                    name.Name.StartsWith("UIAutomation") == false &&
                    name.Name.StartsWith("PresentationFramework") == false &&
                    name.Name.StartsWith("PresentationCore") == false &&
                    name.Name.StartsWith("ReachFramework") == false &&
                    name.Name.StartsWith("WindowsFormsIntegration") == false &&
                    name.Name.StartsWith("WindowsBase") == false)
                {
                    if (name.CodeBase == null)
                    {
                        asm = name.Name + ".dll";
                    }
                    else
                    {
                        asm = name.CodeBase.Replace("file:///", "").Replace("/", "\\");
                    }
                    
                    if (!compilerParams.ReferencedAssemblies.Contains(asm))
                    {
                        compilerParams.ReferencedAssemblies.Add(asm);
                    }
                }
            }
        }

    }
}